home *** CD-ROM | disk | FTP | other *** search
/ X User Tools / X User Tools (O'Reilly and Associates)(1994).ISO / sun4c / archive / timex.z / timex / bin / sumtimex next >
Text File  |  1994-09-27  |  11KB  |  410 lines

  1. #!///////////////////////////////////////////////////////////////////////////usr/STAGE/bin/perl
  2. # PERL hours list writer for TIMEX
  3. do "weekno.perl" || die "Could not do weekno.perl\n";
  4. # Prefixes for some types of project
  5. $privateprefix = "-";
  6. $adjustprefix = "\\+";
  7. # Possible arguments
  8. %args = (
  9.    "fudge", 1,
  10.    "adjust", 0,
  11.    "round", 0,
  12.    "year", 1,
  13.    "name", 1,
  14.    "nameadd", 1,
  15.    "debug", 0,
  16.    "lang", 1,
  17.    "datestyle", 1,
  18.    "minutes", 0,
  19. );
  20. $usage = "Usage: $0 [-year nn ] [-adjust] [-round] [-lang nn] [week]\n"
  21. . "Default week=last week\n";
  22.  
  23. # Set default values for variables
  24. $fudge = 0.5;  # Dividing point for ROUND. Fudgeable.
  25. @pwent = getpwuid($<);
  26. $name = $pwent[6];
  27. $name =~ s/\,.*//;
  28. $timenow = time;
  29. @daynow = localtime($timenow);
  30. $year = $daynow[5];
  31. $lang = $ENV{"LANG"};
  32.  
  33. if ($ENV{"TIMEXDIR"}) {
  34.     $timexdir = $ENV{"TIMEXDIR"};
  35. } else {
  36.     $timexdir = "$ENV{\"HOME\"}/.timex";
  37. }
  38.  
  39. # Set variables from command line and defaults file
  40. &getdefaults("$timexdir/sumdefaults");
  41. &setlanguage();
  42.  
  43. # Find which week to sum for
  44. $week = shift(ARGV);
  45. $oneday = 24 * 60 * 60;
  46. if (!$week) {
  47.    # Default is last week.
  48.    $week = &DATE'weekno($timenow) - 1;
  49. } elsif ($week eq "now") {
  50.    # now is this week
  51.    $week = &DATE'weekno($timenow);
  52. }
  53.    
  54. $timefetch = &DATE'firstinweek($week, $year);
  55.  
  56. for $wday (1..7) {
  57.    @dayfetch = localtime($timefetch);
  58.    if ($datestyle eq "us") {
  59.        $weekdate[$wday] = sprintf("%d/%d", $dayfetch[4] + 1, $dayfetch[3]);
  60.    } elsif ($datestyle eq "de") {
  61.        $weekdate[$wday] = sprintf("%d.%d.", $dayfetch[3], $dayfetch[4] + 1);
  62.    } else {
  63.        $weekdate[$wday] = sprintf("%d/%d", $dayfetch[3], $dayfetch[4] + 1);
  64.    }
  65.    $filename = sprintf("%04d-%02d-%02d",
  66.        1900 + $dayfetch[5], 1 + $dayfetch[4], $dayfetch[3]);
  67.    open(FILE, "$timexdir/$filename") || do { 
  68.        print STDERR "$word{'nofile'} $filename\n";
  69.        $timefetch = $timefetch + $oneday;
  70.        next;
  71.    };
  72.    while (<FILE>) {
  73.        chop;
  74.        if (/^\s*(\d*):(\d*) (.*)/) {
  75.        $project = $3;
  76.            $spent = $1 + $2 / 60;
  77.            $worked{$project} = 1;  # Mark as worked-on this week
  78.            $hours{"$project $wday"} = $spent;
  79.        }
  80.    }
  81.    close FILE;
  82.    $timefetch = $timefetch + $oneday;
  83. }
  84.  
  85. &resum;
  86. if ($hours == 0) {
  87.    print STDERR "$word{'nohours'} $week!\n";
  88.    exit 1;
  89. }
  90.  
  91. if ($adjust) {
  92.    &adjust();
  93. }
  94.  
  95. if ($round) {
  96.    &round;
  97. }
  98.  
  99. # Print the result
  100. if ($nameadd) {
  101.    print "$nameadd $name\n";
  102. } else {
  103.    print "$name\n";
  104. }
  105. print $word{"banner"}, " $week 19$year\n";
  106.  
  107. printf "%-30.30s%6s!%6s%6s%6s%6s%6s%6s%6s\n",
  108.     $word{"project"}, $word{"tot"}, @days[1..7];
  109. printf "%-30.30s%6s!%6s%6s%6s%6s%6s%6s%6s\n",
  110.         $word{"date"}, "", @weekdate[1..7];
  111. print "===============================================================================\n";
  112. for $pro (sort(keys(%hourstot))) {
  113.    if ($hourstot{$pro}) {
  114.       if ($minutes) {
  115.          printf "%-30.30s%3d:%02d!", $pro, int($hourstot{$pro}), int(($hourstot{$pro}-int($hourstot{$pro}))*60);
  116.       } else {
  117.          printf "%-30.30s%6.1f!", $pro, $hourstot{$pro};
  118.       }
  119.       for $day (1..7) {
  120.          if ($hours{"$pro $day"}) {
  121.             if ($minutes) {
  122.                printf "%3d:%02d", int($hours{"$pro $day"}), int(($hours{"$pro $day"}-int($hours{"$pro $day"}))*60);
  123.             } else {
  124.                printf "%6.1f", $hours{"$pro $day"};
  125.             }
  126.          } else {
  127.             printf "%6s", "";
  128.          }
  129.       }
  130.       print "\n";
  131.    }
  132. }
  133. print "===============================================================================\n";
  134. if ($minutes) {
  135.    printf "%-30.30s%3d:%02d!", "TOTAL", int($hours), int(($hours-int($hours))*60);
  136.    for $day (1..7) {
  137.       printf "%3d:%02d", int(@hours[$day]), int((@hours[$day]-int(@hours[$day]))*60);
  138.    }
  139.    printf "\n";
  140.    printf "%-30.30s%3d:%02d\n", "Private poster", int($privhours), int(($privhours-int($privhours))*60);
  141. } else {
  142.    printf "%-30.30s%6.1f!%6.1f%6.1f%6.1f%6.1f%6.1f%6.1f%6.1f\n",
  143.        $word{"total"}, $hours, @hours[1..7];
  144.    printf "%-30.30s%6.1f\n", $word{"private"}, $privhours;
  145. }
  146.  
  147. sub adjust {
  148.    # Adjust - spread + projects across the board
  149.  
  150.    for $pro (keys(%hours)) {
  151.      if ($pro =~ /^$adjustprefix/) {
  152.         $tospread += $hours{$pro};
  153.      }
  154.    }
  155.    $factor = ($tospread/($hours - $tospread)) + 1; 
  156.    printf STDERR "Distributing %5.1f hours across %5.1f hours, factor %5.2f\n",
  157.     $tospread, $hours, $factor;
  158.    # 1) Distribute across projects
  159.    for $pro (keys(%hours)) {
  160.       if ($pro =~ /^$adjustprefix/) {
  161.          $hours{$pro} = 0;
  162.       } elsif ($pro !~ /^$privateprefix/) { # do not spread on private pros
  163.          $hours{$pro} *= $factor;
  164.       }
  165.    }
  166.    &resum("adjust");
  167. }
  168.  
  169. sub round {
  170. # Round all numbers to half-hours
  171.    for $pro (keys(%hours)) {
  172.       $hours{$pro} =  int(($hours{$pro} * 2) + $fudge) / 2; 
  173.    }
  174.    &resum("round");
  175. }
  176.  
  177. sub resum {
  178.    local($why) = @_;
  179.    local($oldhours) = $hours;
  180.    undef %hourstot;
  181.    undef @hours;
  182.    $hours = 0;
  183.    $privhours = 0;
  184.    for $pro (keys(%hours)) {
  185.       # Do NOT sum - marked projects
  186.       if ($pro =~ /^-/) {
  187.          $privhours += $hours{$pro};
  188.       } elsif ($pro =~ /^(.*) (\d)$/) {
  189.          $project = $1; $wday = $2;
  190.          $hourstot{$project} += $hours{$pro};
  191.          $hours[$wday] += $hours{$pro};
  192.          $hours += $hours{$pro};
  193.       } else {
  194.          print STDERR "Bad projectday: $pro\n";
  195.       }
  196.    }
  197.    if ($oldhours && (($hours - $oldhours) ** 2 > 0.1)) {
  198.       print STDERR "$why: Changed total from $oldhours to $hours\n";
  199.    }
  200. }
  201.  
  202. sub getdefaults {
  203.    local($deffile) = @_;
  204.    local($opt, $arg);
  205.    $status = open(DEFAULTS, $deffile);
  206.    if ($status) { # Defaults file found
  207.       while (<DEFAULTS>) {
  208.          chop;
  209.          s/#.*//;
  210.          if (/^(\S+)\s*/) {
  211.             $opt = $1;
  212.             $arg = $';
  213.             &setvar($opt, $arg, "file");
  214.          }
  215.       }
  216.       close(DEFAULTS);
  217.    }
  218.    while ($ARGV[0] =~ /^-(\S+)/) {
  219.       $opt = $1;
  220.       shift(@ARGV);
  221.       $ret = &setvar($opt, $ARGV[0], "ARGV");
  222.       if ($ret == 0) {
  223.          die $usage;
  224.       } elsif ($ret == 2) { # Argument consumed
  225.          shift(@ARGV);
  226.       }
  227.    }
  228. }
  229.  
  230. sub setvar {
  231.    local($opt, $arg, $where) = @_;
  232.    local($ret);
  233.    if (defined($args{$opt})) {
  234.       if ($args{$opt} == 0) {
  235.          eval "\$$opt = 1";
  236.          print STDERR "$where:$opt (set)\n" if $debug;
  237.          $ret = 1;
  238.       } else {
  239.          eval "\$$opt = \"$arg\"";
  240.          print STDERR "$where:$opt = $arg\n" if $debug;
  241.          $ret = 2;
  242.       }
  243.    } else {
  244.      $ret = 0;
  245.    }
  246.    $ret;
  247. }
  248.  
  249. sub setlanguage {
  250.  
  251. # Transform some common language names into ISO 639 language codes
  252. %name2lang = (
  253. "norsk", "no",
  254. "norwegian", "no",
  255. "svenska", "sv", # Yes, the language is "sv" and the country is "se"....
  256. "swedish", "sv",
  257. "se", "sv",
  258. "dansk", "da",
  259. "danish", "da",
  260. "dk", "da", # Domain name mapping for country DK to language da
  261. "eng", "en",
  262. "english", "en",
  263. "fre", "fr",
  264. "ger", "de",
  265. "ita", "it",
  266. # The Big Six (but not int and net) top level domains are assumed to be English
  267. "com", "en",
  268. "edu", "en",
  269. "mil", "en",
  270. "gov", "en",
  271. # US English?
  272. "us", "en",
  273. );
  274.  
  275.    if (!$lang) { 
  276.       $lang = "nolanguage";
  277.       $host = `hostname`;
  278.       chop($host);
  279.       print STDERR "Host(hostname) is $host\n" if $debug;
  280.       if ($host =~ /\.([a-z]{2,3})$/) {
  281.          $lang = $1;
  282.       } else {
  283.          @host = gethostbyname($host);
  284.          $host = $host[0];
  285.          print STDERR "Host(gethostbyname) is $host\n" if $debug;
  286.          if ($host =~ /\.([a-z]{2,3})$/) {
  287.             $lang = $1;
  288.          } else {
  289.             $host = `domainname`; chop $host;
  290.             print STDERR "Domainname is $host\n" if $debug;
  291.             if ($host =~ /\.([a-z]{2,3})$/) {
  292.                $lang = $1;
  293.             }
  294.          }
  295.       }
  296.       print STDERR "Chose language $lang\n" if $debug;
  297.    }
  298.    if ($name2lang{$lang}) {
  299.       $lang = $name2lang{$lang};
  300.    } elsif ($lang =~ /\./) { # Attempt to drop charset trailer if present
  301.       $lang = $`;
  302.       $lang = $name2lang{$lang} if $name2lang{$lang};
  303.    }
  304.  
  305. # Set the strings used in various languages
  306. %lang_no = (
  307. "days", "S°n,Man,Tir,Ons,Tor,Fre,L°r,S°n,Man,Tir,Ons,Tor,Fre",
  308. "banner", "Timeliste for uke",
  309. "total", "Total",
  310. "project", "Prosjekt",
  311. "nofile", "Ingen fil for dag",
  312. "date", "Dato",
  313. "tot", "TOT",
  314. "nohours", "Ingen timer registrert i uke",
  315. );
  316.  
  317. %lang_sv = (
  318. "days", "S÷n,Mσn,Tis,Ons,Tor,Fre,L÷r,S÷n,Mσn,Tis,Ons,Tor,Fre",
  319. "banner", "Timlista f÷r vecka",
  320. "total", "Total",
  321. "project", "Projekt",
  322. "nofile", "Ingen projektfil f÷r dag",
  323. "date", "Datum",
  324. "tot", "TOT",
  325. "nohours", "Inga timmar registrerade i vecka",
  326. );
  327.  
  328. %lang_en = (
  329. "days", "Sun,Mon,Tue,Wed,Thu,Fri,Sat,Sun,Mon,Tue,Wed,Thu,Fri",
  330. "banner", "Hours worked for week",
  331. "total", "Total",
  332. "project", "Project",
  333. "nofile", "No file for day",
  334. "date", "Date",
  335. "tot", "TOT",
  336. "nohours", "No hours worked in week",
  337. );
  338.  
  339. %lang_fr = (
  340. "days", "Dim,Lun,Mar,Mer,Jeu,Ven,Sam,Dim,Lun,Mar,Mer,Jeu,Ven",
  341. "banner", "Horaire de semaine",
  342. "total", "Total",
  343. "project", "Projet",
  344. "date", "Date",
  345. "nofile", "Pas trouve de fichier pour le",
  346. "tot", "TOTAL",
  347. );
  348.  
  349. %lang_de = (
  350. "days", "So,Mo,Di,Mi,Do,Fr,Sa,So,Mo,Di,Mi,Do,Fr",
  351. "banner", "Wochenzeitplan Woche",
  352. "total", "Summe",
  353. "project", "Projekt",
  354. "date", "Datum",
  355. "tot", "SUM",
  356. "nofile", "Keine Informationen fⁿr das Datum",
  357. "nohours", "Keine Informationen fⁿr die Woche",
  358. );
  359.  
  360. %lang_it = (
  361. "days", "Dom,Lun,Mar,Mer,Gio,Ven,Sab,Dom,Lun,Mar,Mer,Gio,Ven",
  362. "banner", "Il tempo lista per settimana",
  363. "total", "Total",
  364. "project", "Project",
  365. );
  366.  
  367. %lang_da = (
  368. "days", "S°n,Man,Tir,Ons,Tor,Fre,L°r,S°n,Man,Tir,Ons,Tor,Fre",
  369. "banner", "Timeliste for uge",
  370. "total", "Total",
  371. "project", "Projekt",
  372. "nofile", "Ingen fil for dag",
  373. "date", "Dato",
  374. "tot", "Total",
  375. "nohours", "Ingen timer registreret i uge",
  376. );
  377.  
  378. %word = (
  379.   "days", "Sun,Mon,Tue,Wed,Thu,Fri,Sat,Sun,Mon,Tue,Wed,Thu,Fri",
  380.   "banner", "*Hours worked week",
  381.   "nofile", "*No file for day",
  382.   "project", "*Project",
  383.   "total", "*TOTAL",
  384.   "tot", "*TOT",
  385.   "date", "*Date",
  386.   "nohours", "*No hours worked in week",
  387. );
  388.  
  389.  
  390.    %langword = eval "\%lang_$lang";
  391.    print STDERR "$@\n" if $@;
  392.    if (!%langword) {
  393.       print STDERR "Language $lang unknown, using English (en)\n",
  394.                    "Use command line switch -lang xx to force another\n";
  395.       $lang = "en";
  396.       %langword = %lang_en;
  397.    }
  398.    #if (!%langword) {
  399.    for $word (keys(%word)) {
  400.       if ($langword{$word}) {
  401.          print STDERR "$word = $langword{$word}\n" if $debug;
  402.          $word{$word} = $langword{$word};
  403.       } else {
  404.          print STDERR "\$lang_$lang{$word} not found\n" if $debug;
  405.       }
  406.    }
  407.    @days = split(/,/, $word{"days"});
  408. }
  409.  
  410.